Android14 显示系统剖析6 ———— BufferQueueProducer 获取帧缓存过程分析

7/1/2024

本文基于 aosp android-14.0.0_r15 版本讲解。

在上一节我们分析了 BLASTBufferQueue 的整个初始化过程,知道了其内部成员组成与相互关系。

本节主要分析 Producer 获取帧缓存的过程。

# 1. 配置 BBQBufferQueueProducer 对象

接着分析示例程序的后续代码:

    // 获取到 GraphicBuffer 的生产者
    sp<IGraphicBufferProducer> igbProducer;
    // 返回前面 new 的 BBQBufferQueueProducer
    igbProducer = mBlastBufferQueue->getIGraphicBufferProducer();
    // 设置最大出队列 buffer 数量
    igbProducer->setMaxDequeuedBufferCount(2);
    IGraphicBufferProducer::QueueBufferOutput qbOutput;
    // 给 BufferQuequCore 设置一些参数
    igbProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbOutput);
1
2
3
4
5
6
7
8
9

getIGraphicBufferProducer 函数拿到之前 new 的 BBQBufferQueueProducer 指针,然后调用两个函数配置 BBQBufferQueueProducer 对象。

  • setMaxDequeuedBufferCount(2):设置最大出队列 buffer 数量
  • connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbOutput):给 BufferQueqeuCore 设置一些参数

接下来我们来分析这两个函数的具体实现。

# 1.1 setMaxDequeuedBufferCount 实现分析

setMaxDequeuedBufferCount 的实现如下:

status_t BufferQueueProducer::setMaxDequeuedBufferCount(
        int maxDequeuedBuffers) {
    int maxBufferCount;
    return setMaxDequeuedBufferCount(maxDequeuedBuffers, &maxBufferCount);
}
1
2
3
4
5

接着调用另一个重载:

status_t BufferQueueProducer::setMaxDequeuedBufferCount(int maxDequeuedBuffers,
                                                        int* maxBufferCount) {
    ATRACE_FORMAT("%s(%d)", __func__, maxDequeuedBuffers);
    BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
            maxDequeuedBuffers);

    sp<IConsumerListener> listener;
    { // Autolock scope
        std::unique_lock<std::mutex> lock(mCore->mMutex);
        mCore->waitWhileAllocatingLocked(lock);

        if (mCore->mIsAbandoned) {
            BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
                    "abandoned");
            return NO_INIT;
        }

        *maxBufferCount = mCore->getMaxBufferCountLocked();

        if (maxDequeuedBuffers == mCore->mMaxDequeuedBufferCount) {
            return NO_ERROR;
        }

        // The new maxDequeuedBuffer count should not be violated by the number
        // of currently dequeued buffers
        int dequeuedCount = 0;
        for (int s : mCore->mActiveBuffers) {
            if (mSlots[s].mBufferState.isDequeued()) {
                dequeuedCount++;
            }
        }
        if (dequeuedCount > maxDequeuedBuffers) {
            BQ_LOGE("setMaxDequeuedBufferCount: the requested maxDequeuedBuffer"
                    "count (%d) exceeds the current dequeued buffer count (%d)",
                    maxDequeuedBuffers, dequeuedCount);
            return BAD_VALUE;
        }

        int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
        bufferCount += maxDequeuedBuffers;

        if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
            BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
                    "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
            return BAD_VALUE;
        }

        const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
        if (bufferCount < minBufferSlots) {
            BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
                    "less than minimum %d", bufferCount, minBufferSlots);
            return BAD_VALUE;
        }

        if (bufferCount > mCore->mMaxBufferCount) {
            BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
                    "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
                    "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers,
                    mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
                    mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock);
            return BAD_VALUE;
        }

        int delta = maxDequeuedBuffers - mCore->mMaxDequeuedBufferCount;
        if (!mCore->adjustAvailableSlotsLocked(delta)) {
            return BAD_VALUE;
        }

        // 关注点
        // 核心就是给 BufferQueueCore 的 mMaxDequeuedBufferCount 赋值为参数 maxDequeuedBuffers
        mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
        *maxBufferCount = mCore->getMaxBufferCountLocked();
        VALIDATE_CONSISTENCY();
        if (delta < 0) {
            listener = mCore->mConsumerListener;
        }
        mCore->mDequeueCondition.notify_all();
    } // Autolock scope

    // Call back without lock held
    if (listener != nullptr) {
        listener->onBuffersReleased();
    }

    return NO_ERROR;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

代码很多,包括一些计算、比较和初始化,我们关心最关键的一点,给 BufferQueueCore 的 mMaxDequeuedBufferCount 赋值为参数 maxDequeuedBuffers。也就是设置 BufferQueueCore 最多能出栈两个 buffer。

那么在后续申请 buffer 的分析中,我们应该着重看看 mMaxDequeuedBufferCount 这个变量是怎么限制 buffer 的数量的。

# 1.2 connect 函数实现分析

接着看 connect 函数实现:

    status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
                     QueueBufferOutput* output) override {

        if (!listener) {
            // listener 为空
            return BufferQueueProducer::connect(listener, api, producerControlledByApp, output);
        }

        // listener 不为空
        return BufferQueueProducer::connect(new AsyncProducerListener(listener), api,
                                            producerControlledByApp, output);
    }
1
2
3
4
5
6
7
8
9
10
11
12

这里传入的 listener 是一个 StubProducerListener 对象,接着调用父类的 BufferQueueProducer::connect 函数:

status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
        int api, bool producerControlledByApp, QueueBufferOutput *output) {
    ATRACE_CALL();
    std::lock_guard<std::mutex> lock(mCore->mMutex);
    mConsumerName = mCore->mConsumerName;
    BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
            producerControlledByApp ? "true" : "false");

    if (mCore->mIsAbandoned) {
        BQ_LOGE("connect: BufferQueue has been abandoned");
        return NO_INIT;
    }

    if (mCore->mConsumerListener == nullptr) {
        BQ_LOGE("connect: BufferQueue has no consumer");
        return NO_INIT;
    }

    if (output == nullptr) {
        BQ_LOGE("connect: output was NULL");
        return BAD_VALUE;
    }

    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("connect: already connected (cur=%d req=%d)",
                mCore->mConnectedApi, api);
        return BAD_VALUE;
    }

    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
            mDequeueTimeout < 0 ?
            mCore->mConsumerControlledByApp && producerControlledByApp : false,
            mCore->mMaxBufferCount) -
            mCore->getMaxBufferCountLocked();
    if (!mCore->adjustAvailableSlotsLocked(delta)) {
        BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
                "slots. Delta = %d", delta);
        return BAD_VALUE;
    }

    int status = NO_ERROR;
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
        case NATIVE_WINDOW_API_CPU: // 走这个 case
        case NATIVE_WINDOW_API_MEDIA:
        case NATIVE_WINDOW_API_CAMERA:
            mCore->mConnectedApi = api;

            output->width = mCore->mDefaultWidth;
            output->height = mCore->mDefaultHeight;
            output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
            output->numPendingBuffers =
                    static_cast<uint32_t>(mCore->mQueue.size());
            output->nextFrameNumber = mCore->mFrameCounter + 1;
            output->bufferReplaced = false;
            output->maxBufferCount = mCore->mMaxBufferCount;

            if (listener != nullptr) {
                // Set up a death notification so that we can disconnect
                // automatically if the remote producer dies
#ifndef NO_BINDER
                if (IInterface::asBinder(listener)->remoteBinder() != nullptr) {
                    status = IInterface::asBinder(listener)->linkToDeath(
                            static_cast<IBinder::DeathRecipient*>(this));
                    if (status != NO_ERROR) {
                        BQ_LOGE("connect: linkToDeath failed: %s (%d)",
                                strerror(-status), status);
                    }
                    mCore->mLinkedToDeath = listener;
                }
#endif
                mCore->mConnectedProducerListener = listener;
                mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
            }
            break;
        default:
            BQ_LOGE("connect: unknown API %d", api);
            status = BAD_VALUE;
            break;
    }
    mCore->mConnectedPid = BufferQueueThreadState::getCallingPid();
    mCore->mBufferHasBeenQueued = false;
    mCore->mDequeueBufferCannotBlock = false;
    mCore->mQueueBufferCanDrop = false;
    mCore->mLegacyBufferDrop = true;
    if (mCore->mConsumerControlledByApp && producerControlledByApp) {
        mCore->mDequeueBufferCannotBlock = mDequeueTimeout < 0;
        mCore->mQueueBufferCanDrop = mDequeueTimeout <= 0;
    }

    mCore->mAllowAllocation = true;
    VALIDATE_CONSISTENCY();
    return status;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

connect 其实就是配置 BufferQueueCore 和 QueueBufferOutput 两个对象。BufferQueueCore 用于管理帧缓存,QueueBufferOutput 的任务就是把 BufferQueueCore 内部的一些参数传递给 App。

# 2. Producer 对象 dequeueBuffer 过程分析

接下来我们就来分析 Producer 对象获取帧缓存的过程:

接着看示例程序的后续代码:

        int slot;
        sp<Fence> fence;
        sp<GraphicBuffer> buf;
        
        // 1. dequeue buffer
        igbProducer->dequeueBuffer(&slot, &fence, nativeSurface->width(), nativeSurface->height(),
                                              PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
                                              nullptr, nullptr);
        igbProducer->requestBuffer(slot, &buf);
1
2
3
4
5
6
7
8
9

dequeueBuffer 函数的功能是从 BufferQueueCore 获取 BufferSlot。通过 slot 返回结果,slot 是 BufferSlot 对象在 mSlot 数组中的索引。

另外,需要注意的是这里传入了一个 Fence 指针,是一个空指针,应该是做返回值用的,Fence 是内核提供的不同硬件间同步机制,在 userspace 层我们可以将它视为是一把锁,它代表了某个硬件对共享资源的占用情况。

对一个 Fence 对象有两种操作, signal 和 wait,举个接下来就要看到的栗子:

当 App 拿到 buffer 和 fence 后,就可以调用 GPU 开始绘制,所谓绘制,就是把各种指令转换为需要显示的内存内容并写入 buffer,这个过程通常比较耗时,如果在这里等待就浪费了 cpu 资源,所以程序通知 gpu 开始绘制后(gpu 绘制是一个异步过程),就把 buffer 和 Fence 通过 binder 传递给 Sf 准备合成显示,sf 这个时候其实不知道 gpu 的绘制完成没有,就调用 fence.wait 阻塞等待,当 gpu 完成绘制以后,就会调用 fence.sigal,这个时候 sf 就会从 fence.wait 的阻塞中被唤醒进行后续的 buffer 合成工作。

20240703212827

图片来自 https://www.jianshu.com/p/3c61375cc15b

了解了 fence 以后,我们接着来看 dequeueBuffer() 函数,dequeueBuffer 用于从 BufferQueueCore 的 mSlots 中获取到一个 buffer 和 一个 fence,准备着给 App 绘制用。

dequeueBuffer() 默认优先从 mFreeBuffers 中获取 slot,因为 mFreeBuffers 中的 slot 已经有 buffer 与之绑定过了,这样就不用再重新分配 buffer 了。然后以 slot 为索引在 mSlot 数组中找到对应的 BufferSlot 对象,并将 BufferSlot 对象的状态从 FREE 修改为 DEQUEUED,然后将 BufferSlot 的索引插入 ActiveBuffers 中,整个过程用动图描述如下如下:

2019081121012540

动图来自 https://blog.csdn.net/hexiaolong2009/article/details/99225637

如果 mFreeBuffers 为空,则从 mFreeSlots 中获取 slot:

20190811210206758

动图来自 https://blog.csdn.net/hexiaolong2009/article/details/99225637

接下来,我们来看 dequeueBuffer 函数的具体实现:

status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
                                            uint32_t width, uint32_t height, PixelFormat format,
                                            uint64_t usage, uint64_t* outBufferAge,
                                            FrameEventHistoryDelta* outTimestamps) {
        // ......                                             
        // 寻找BufferSlot
        int found = BufferItem::INVALID_BUFFER_SLOT;

        // 一个 while 循环,反复去获取 BufferSlot,直到获取到为止
        while (found == BufferItem::INVALID_BUFFER_SLOT) {


            // 从 mSlots 获取到可用的 BufferSlot,可用的 BufferSlot 在 mSlots 中的 index 保存在 found 中
            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);
            if (status != NO_ERROR) {
                return status;
            }

            // This should not happen
            if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
                BQ_LOGE("dequeueBuffer: no available buffer slots");
                return -EBUSY;
            }

            //获取 found 索引对应的 BufferSlot 及对应的 GraphicBuffer。后面需要为该 GraphicBuffer 分配空间
            const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);

            // If we are not allowed to allocate new buffers,
            // waitForFreeSlotThenRelock must have returned a slot containing a
            // buffer. If this buffer would require reallocation to meet the
            // requested attributes, we free it and attempt to get another one.
            // mCore->mAllowAllocation 初始值是 true
            // 在不允许分配新的buffer时,waitForFreeSlotThenRelock必须返回一个绑定GraphicBuffer的slot.
            // 如果这个buffer需要重新分配来满足新要求的属性,我们必须释放它然后再重新请求一个。
            if (!mCore->mAllowAllocation) { 
                if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
                    if (mCore->mSharedBufferSlot == found) {
                        BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer");
                        return BAD_VALUE;
                    }
                    mCore->mFreeSlots.insert(found);
                    mCore->clearBufferSlotLocked(found);
                    found = BufferItem::INVALID_BUFFER_SLOT;
                    continue;
                }
            }
        }

        // 跳出 while 就是找到了一个合适的 BufferSlot
        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
        
        if (mCore->mSharedBufferSlot == found &&
                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
            BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
                    "buffer");

            return BAD_VALUE;
        }

        // mCore->mSharedBufferSlot 的初始值为 INVALID_BUFFER_SLOT 
        // 如果不是共享 buffer,就把这个 BufferSlot 对应的下标,加入到 mActiveBuffers 中
        if (mCore->mSharedBufferSlot != found) {
            mCore->mActiveBuffers.insert(found);
        }

        // 返回值
        *outSlot = found;
        ATRACE_BUFFER_INDEX(found);

        attachedByConsumer = mSlots[found].mNeedsReallocation;
        mSlots[found].mNeedsReallocation = false;

        // 修改 BufferSlot 的状态 FREE -> DEQUEUED
        mSlots[found].mBufferState.dequeue();

        if ((buffer == nullptr) ||
                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) // 需要分配内存
        {
            if (CC_UNLIKELY(ATRACE_ENABLED())) {
                if (buffer == nullptr) {
                    ATRACE_FORMAT_INSTANT("%s buffer reallocation: null", mConsumerName.string());
                } else {
                    ATRACE_FORMAT_INSTANT("%s buffer reallocation actual %dx%d format:%d "
                                          "layerCount:%d "
                                          "usage:%d requested: %dx%d format:%d layerCount:%d "
                                          "usage:%d ",
                                          mConsumerName.string(), width, height, format,
                                          BQ_LAYER_COUNT, usage, buffer->getWidth(),
                                          buffer->getHeight(), buffer->getPixelFormat(),
                                          buffer->getLayerCount(), buffer->getUsage());
                }
            }

            // 设置一些标志位
            mSlots[found].mAcquireCalled = false;
            mSlots[found].mGraphicBuffer = nullptr;
            mSlots[found].mRequestBufferCalled = false;
            mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
            mSlots[found].mFence = Fence::NO_FENCE;
            mCore->mBufferAge = 0;
            mCore->mIsAllocating = true;

            // 这个标志位后面要用
            returnFlags |= BUFFER_NEEDS_REALLOCATION;
        } else { // 不需要分配内存的情况
            // We add 1 because that will be the frame number when this buffer
            // is queued
            mCore->mBufferAge = mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
        }

        BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
                mCore->mBufferAge);

        if (CC_UNLIKELY(mSlots[found].mFence == nullptr)) {
            BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
                    "slot=%d w=%d h=%d format=%u",
                    found, buffer->width, buffer->height, buffer->format);
        }

        // 因为GraphicBuffer 最终是要到 Gpu 去消费,而当前的操作都是在 cpu,
        // 为了同步cpu和Gpu对同一数据的使用,产生了这中Fence机制
        eglDisplay = mSlots[found].mEglDisplay;
        eglFence = mSlots[found].mEglFence;
        // Don't return a fence in shared buffer mode, except for the first
        // frame.
        // mSharedBufferMode 默认值是 false
        // 这里赋值为 BufferSlot 的 mFence
        *outFence = (mCore->mSharedBufferMode &&
                mCore->mSharedBufferSlot == found) ?
                Fence::NO_FENCE : mSlots[found].mFence;
        mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
        mSlots[found].mFence = Fence::NO_FENCE;

        // If shared buffer mode has just been enabled, cache the slot of the
        // first buffer that is dequeued and mark it as the shared buffer.
        if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
                BufferQueueCore::INVALID_BUFFER_SLOT) {
            mCore->mSharedBufferSlot = found;
            mSlots[found].mBufferState.mShared = true;
        }

        if (!(returnFlags & BUFFER_NEEDS_REALLOCATION)) { // 不要分配内存情况的回调
            if (mCore->mConsumerListener != nullptr) {
                mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId());
            }
        }
    } // Autolock scope
    

    // 前面赋值了标志位,需要分配内存的情况
    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {

        BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);

        // Slot 没有和 GraphicBuffer 进行绑定, 那么就会先创建一个 GraphicBuffer
        // 使用 Gralloc HAL 进行内存分配,分配内存的细节在后续章节讲解
        sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
                width, height, format, BQ_LAYER_COUNT, usage,
                {mConsumerName.string(), mConsumerName.size()});

        status_t error = graphicBuffer->initCheck();

        { // Autolock scope
            std::lock_guard<std::mutex> lock(mCore->mMutex);

            if (error == NO_ERROR && !mCore->mIsAbandoned) {
                graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
                // 分配成功,把 GraphicBuffer 与对应的 BufferSlot 进行绑定
                mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
                if (mCore->mConsumerListener != nullptr) {
                    mCore->mConsumerListener->onFrameDequeued(
                            mSlots[*outSlot].mGraphicBuffer->getId());
                }
            }
             // 分配完成,唤醒等待的线程
            mCore->mIsAllocating = false;
            mCore->mIsAllocatingCondition.notify_all();

            if (error != NO_ERROR) {
                mCore->mFreeSlots.insert(*outSlot);
                mCore->clearBufferSlotLocked(*outSlot);
                BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
                return error;
            }

            if (mCore->mIsAbandoned) {
                mCore->mFreeSlots.insert(*outSlot);
                mCore->clearBufferSlotLocked(*outSlot);
                BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
                return NO_INIT;
            }

            VALIDATE_CONSISTENCY();
        } // Autolock scope
    }

   //......

    return returnFlags;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

dequeueBuffer 函数主要完成了以下工作:

  1. 寻找状态为 FREE 的可用的 BufferSlot,主要是调用 waitForFreeSlotThenRelock,去 mFreeBuffers 和 mFreeSlots 中查找。
  2. 找到可用的 BufferSlot 后,先把其对应的 index 添加到 mActiveBuffer 集合中,标示为活跃状态,并且设置为 DEQUEUED 状态;
  3. 如果找到的 BufferSlot 的 GraphicBuffer 为空或者需要重新申请,则把 BufferSlot 的参数初始化;
  4. 如果需要重新创建 GraphicBuffer,则 new 一个 GraphicBuffer 对象,这个过程中会调用 Gralloc 分配内存,接着将 GraphicBuffer 对象绑定到对应的 BufferSlot;
  5. 其它操作,比如唤醒等待 buffer 分配完成的线程;

另外这里还会将找到的 BufferSlot 的 mFence 成员返回给 App。

接下来我们来看其中几个比较重要的过程.

waitForFreeSlotThenRelock 用于找到一个状态为 FREE 的可用的 BufferSlot,其实现如下:

status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,
        std::unique_lock<std::mutex>& lock, int* found) const {
    auto callerString = (caller == FreeSlotCaller::Dequeue) ?
            "dequeueBuffer" : "attachBuffer";
    bool tryAgain = true;
    while (tryAgain) {
        if (mCore->mIsAbandoned) {
            BQ_LOGE("%s: BufferQueue has been abandoned", callerString);
            return NO_INIT;
        }

        int dequeuedCount = 0;
        int acquiredCount = 0;

        // 计算
        for (int s : mCore->mActiveBuffers) {
            if (mSlots[s].mBufferState.isDequeued()) {
                ++dequeuedCount;
            }
            if (mSlots[s].mBufferState.isAcquired()) {
                ++acquiredCount;
            }
        }

        // Producers are not allowed to dequeue more than
        // mMaxDequeuedBufferCount buffers.
        // This check is only done if a buffer has already been queued

        // mMaxDequeuedBufferCount 判断,不能超出了
        // 前面代码设置了这个值
        if (mCore->mBufferHasBeenQueued &&
                dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
            // Supress error logs when timeout is non-negative.
            if (mDequeueTimeout < 0) {
                BQ_LOGE("%s: attempting to exceed the max dequeued buffer "
                        "count (%d)", callerString,
                        mCore->mMaxDequeuedBufferCount);
            }
            return INVALID_OPERATION;
        }

        *found = BufferQueueCore::INVALID_BUFFER_SLOT;

        // If we disconnect and reconnect quickly, we can be in a state where
        // our slots are empty but we have many buffers in the queue. This can
        // cause us to run out of memory if we outrun the consumer. Wait here if
        // it looks like we have too many buffers queued up.
        const int maxBufferCount = mCore->getMaxBufferCountLocked();
        bool tooManyBuffers = mCore->mQueue.size()
                            > static_cast<size_t>(maxBufferCount);
        if (tooManyBuffers) {
            BQ_LOGV("%s: queue size is %zu, waiting", callerString,
                    mCore->mQueue.size());
        } else {
            // If in shared buffer mode and a shared buffer exists, always
            // return it.
            if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot !=
                    BufferQueueCore::INVALID_BUFFER_SLOT) {
                *found = mCore->mSharedBufferSlot;
            } else {
                // 重点关注这里
                if (caller == FreeSlotCaller::Dequeue) { // 走这个分支
                    // If we're calling this from dequeue, prefer free buffers
                    // 先从 mFreeBuffers 中取 slot
                    int slot = getFreeBufferLocked();
                    if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
                        *found = slot;
                    } else if (mCore->mAllowAllocation) {
                        // FreeBuffers 中没有,再从 mFreeSlots 中取
                        *found = getFreeSlotLocked();
                    }
                } else {
                    // If we're calling this from attach, prefer free slots
                    int slot = getFreeSlotLocked();
                    if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
                        *found = slot;
                    } else {
                        *found = getFreeBufferLocked();
                    }
                }
            }
        }

        // If no buffer is found, or if the queue has too many buffers
        // outstanding, wait for a buffer to be acquired or released, or for the
        // max buffer count to change.
        tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
                   tooManyBuffers;
        if (tryAgain) {
            // Return an error if we're in non-blocking mode (producer and
            // consumer are controlled by the application).
            // However, the consumer is allowed to briefly acquire an extra
            // buffer (which could cause us to have to wait here), which is
            // okay, since it is only used to implement an atomic acquire +
            // release (e.g., in GLConsumer::updateTexImage())
            if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
                    (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
                return WOULD_BLOCK;
            }
            if (mDequeueTimeout >= 0) {
                std::cv_status result = mCore->mDequeueCondition.wait_for(lock,
                        std::chrono::nanoseconds(mDequeueTimeout));
                if (result == std::cv_status::timeout) {
                    return TIMED_OUT;
                }
            } else {
                mCore->mDequeueCondition.wait(lock);
            }
        }
    } // while (tryAgain)

    return NO_ERROR;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

其中一堆判断一堆记录,核心的主要是 getFreeBufferLockedgetFreeSlotLocked 两个函数:

getFreeBufferLocked 就是从 mFreeBuffers 的头部去取一个数据:

int BufferQueueProducer::getFreeBufferLocked() const {
    if (mCore->mFreeBuffers.empty()) {
        return BufferQueueCore::INVALID_BUFFER_SLOT;
    }
    int slot = mCore->mFreeBuffers.front();
    mCore->mFreeBuffers.pop_front();
    return slot;
}
1
2
3
4
5
6
7
8

getFreeBufferLocked 就是从 mFreeSlots 的头部去取一个数据:

// mFreeSlots 是一个 vector
// 就是从前往后取,取完后删除
int BufferQueueProducer::getFreeSlotLocked() const {
    if (mCore->mFreeSlots.empty()) {
        return BufferQueueCore::INVALID_BUFFER_SLOT;
    }
    int slot = *(mCore->mFreeSlots.begin());
    mCore->mFreeSlots.erase(slot);
    return slot;
}
1
2
3
4
5
6
7
8
9
10

一般是先从 mFreeBuffers 中取,因为这里的 BufferSlot 都已经分配过 GraphicBuffer 了,mFreeBuffers 中没有的话就从 mFreeSlots 中取。

我们接着看 requestBuffer 的实现:

status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
    ATRACE_CALL();
    BQ_LOGV("requestBuffer: slot %d", slot);
    std::lock_guard<std::mutex> lock(mCore->mMutex);

    if (mCore->mIsAbandoned) {
        BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
        return NO_INIT;
    }

    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
        return NO_INIT;
    }

    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
        BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
        return BAD_VALUE;
    } else if (!mSlots[slot].mBufferState.isDequeued()) {
        BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
                "(state = %s)", slot, mSlots[slot].mBufferState.string());
        return BAD_VALUE;
    }

    mSlots[slot].mRequestBufferCalled = true;
    *buf = mSlots[slot].mGraphicBuffer;
    return NO_ERROR;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

requestBuffer 比较简单,就是把 BufferSlot 中的 GraphicBuffer 取出返回。

接着看后续的示例代码:

        // int waitResult = fence->waitForever("dequeueBuffer_EmptyNative");
        if (waitResult != OK) {
            ALOGE("dequeueBuffer_EmptyNative: Fence::wait returned an error: %d", waitResult);
            break;
        }  

        uint8_t* img = nullptr;
        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
        if (err != NO_ERROR) {
            ALOGE("error: lock failed: %s (%d)", strerror(-err), -err);
            break;
        }
        int countFrame = 0;
        countFrame = (countFrame+1)%3;
        
        // 理论上,渲染 buffer 应该在单独的线程中进行
        // 还需要构建一个 Fence 对象,渲染完成后调用 fence.signal
        // 示例程序为了便于理解上手,都做了简化。
        fillRGBA8Buffer(img, resolution.getWidth(), resolution.getHeight(), buf->getStride(),
                        countFrame == 0 ? 255 : 0,
                        countFrame == 1 ? 255 : 0,
                        countFrame == 2 ? 255 : 0);

        err = buf->unlock();

        //是不是差一个 fence->signal ?

        if (err != NO_ERROR) {
            ALOGE("error: unlock failed: %s (%d)", strerror(-err), -err);
            break;
        }
        
        // 3. queue the buffer to display
        IGraphicBufferProducer::QueueBufferOutput qbOutput;
        // 这里最后一个参数应该是渲染过程构建的 fence 对象
        // 这里做了简化,直接传的 Fence::NO_FENCE
        IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
                                                       HAL_DATASPACE_UNKNOWN, {},
                                                       NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
                                                       Fence::NO_FENCE);
        igbProducer->queueBuffer(slot, input, &qbOutput);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  • 调用 buffer 的 lock 函数获取到 buffer 的用户态指针
  • 接着调用 fillRGBA8Buffer 填充 buffer
  • 然后调用 buffer 的 unlock
  • 最后 queueBuffer 将填充好的 buffer 提交给 bufferQueue

# 2.1 GraphicBuffer 的初始化过程分析

前文说到,如果一个 BufferSlot 还没有分配内存,就会去初始化一个 GraphicBuffer 对象。

GraphicBuffer 的定义如下:

// /frameworks/native/libs/ui/include/ui/GraphicBuffer.h
class GraphicBuffer
    : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
      public Flattenable<GraphicBuffer>
{       
    // ......
    GraphicBufferMapper& mBufferMapper;
    // ......
}
1
2
3
4
5
6
7
8
9

继承自 ANativeObjectBase 和 Flattenable

Flattenable 用于支持序列化,让 GraphicBuffer 可以通过 Binder 在进程之间传递

ANativeObjectBase 是一个模板类:

template <typename NATIVE_TYPE, typename TYPE, typename REF,
        typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{
    //......
}
1
2
3
4
5
6

ANativeObjectBase 展开后,可以看出 ANativeObjectBase 继承自 ANativeWindowBuffer 和 RefBase

RefBase 使得 GraphicBuffer 可以通过引用计数来管理指针。

// /frameworks/native/libs/nativebase/include/nativebase/nativebase.h

typedef struct ANativeWindowBuffer ANativeWindowBuffer;

typedef struct ANativeWindowBuffer
{
#ifdef __cplusplus
    ANativeWindowBuffer() {
        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
        common.version = sizeof(ANativeWindowBuffer);
        memset(common.reserved, 0, sizeof(common.reserved));
    }

    // Implement the methods that sp<ANativeWindowBuffer> expects so that it
    // can be used to automatically refcount ANativeWindowBuffer's.
    void incStrong(const void* /*id*/) const {
        common.incRef(const_cast<android_native_base_t*>(&common));
    }
    void decStrong(const void* /*id*/) const {
        common.decRef(const_cast<android_native_base_t*>(&common));
    }
#endif

    struct android_native_base_t common;

    int width;
    int height;
    int stride;
    int format;
    int usage_deprecated;
    uintptr_t layerCount;

    void* reserved[1];

    // 核心
    const native_handle_t* handle;
    uint64_t usage;

    // we needed extra space for storing the 64-bits usage flags
    // the number of slots to use from reserved_proc depends on the
    // architecture.
    void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
} ANativeWindowBuffer_t;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

ANativeWindowBuffer 的核心成员是 native_handle,native_handle 用于描述一块内存,可跨平台使用。

// system/core/libcutils/include/cutils/native_handle.h
typedef struct native_handle  
{  
    int version;        //设置为结构体 native_handle 的大小,用来标识结构体 native_handle_t 的版本
    int numFds;         //标识结构体 native_handle_t所 包含的文件描述符的个数,这些文件描述符保存在成员变量 data 所指向的一块缓冲区中
    int numInts;        //表示结构体 native_handle_t 所包含的整数值的个数,这些整数保存在成员变量data所指向的一块缓冲区中
    int data[0];        //指向的一块缓冲区
} native_handle_t;  
1
2
3
4
5
6
7
8

private_handle_t 是 native_handle 的子类,是 gralloc 中对用于描述一块内存的结构体,不同芯片厂商的实现可能不同,不能跨平台使用。

下面是 aosp 中找到的一种实现:

// C 定义
// hardware/libhardware/modules/gralloc/gralloc_priv.h
struct private_handle_t {
    struct native_handle nativeHandle;
    enum {
        PRIV_FLAGS_FRAMEBUFFER = 0x00000001
    };
    int     fd; //指向一个文件描述符,这个文件描述符指向一块内存
    int     magic;
    int     flags;//用来描述一个缓冲区的标志,当一个缓冲区的标志值等于PRIV_FLAGS_FRAMEBUFFER的时候,就表示它是在帧缓冲区中分配的。
    int     size;//用来描述一个缓冲区的大小
    int     offset;//用来描述一个缓冲区的偏移地址
    int     base;//用来描述一个缓冲区的实际地址
    int     pid;//用来描述一个缓冲区的创建者的PID
    
    // 因为native_handle的data成员是一个大小为0的数组,所以data[0]其实就是指向了fd,data[1]指向magic,以此类推.  
    // 上面提到我们可以把native_handle看成是一个纯虚的基类,那么在private_handle_t这个派生类中,numFds=1 numInts=6.      
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Cpp 定义
struct private_handle_t : public native_handle {
    enum {
        PRIV_FLAGS_FRAMEBUFFER = 0x00000001
    };
    int     fd; //指向一个文件描述符,这个文件描述符指向一块内存
    int     magic;//指向一个魔数,它的值由静态成员变量sMagic来指定,用来标识一个private_handle_t结构体。
    int     flags;//用来描述一个缓冲区的标志,它的值要么等于0,要么等于PRIV_FLAGS_FRAMEBUFFER
    int     size;//用来描述一个缓冲区的大小。
    int     offset;//用来描述一个缓冲区的偏移地址。
    int     base;//用来描述一个缓冲区的实际地址,它是通过成员变量offset来计算得到的。
    int     pid;//用来描述一个缓冲区的创建者的PID。
    static const int sNumInts = 6; //包含有6个整数
    static const int sNumFds = 1; //包含有1个文件描述符
    static const int sMagic = 0x3141592;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

private_handle_t 的核心就是有一个 fd 成员,fd 就是具体 buffer 的索引。

了解了 GraphicBuffer 的整体结构以后,我们来看它的初始化过程。


// /frameworks/native/libs/ui/GraphicBuffer.cpp
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
                             uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
      : GraphicBuffer() {
    mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
                              std::move(requestorName));
}
1
2
3
4
5
6
7
8

先调用无参数构造函数重载:

GraphicBuffer::GraphicBuffer()
    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
{
    width  =
    height =
    stride =
    format =
    usage_deprecated = 0;
    usage  = 0;
    layerCount = 0;
    handle = nullptr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

这里主要是对内部成员做初始化。其中 mBufferMapper 会通过 GraphicBufferMapper::get() 初始化,GraphicBufferMapper 是一个单例类,其定义如下:

class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
{
public:
    enum Version {
        GRALLOC_2 = 2,
        GRALLOC_3,
        GRALLOC_4,
        GRALLOC_5,
    };
    static void preloadHal();
    static inline GraphicBufferMapper& get() { return getInstance(); }

    void dumpBuffer(buffer_handle_t bufferHandle, std::string& result, bool less = true) const;
    static void dumpBufferToSystemLog(buffer_handle_t bufferHandle, bool less = true);

    // The imported outHandle must be freed with freeBuffer when no longer
    // needed. rawHandle is owned by the caller.
    status_t importBuffer(const native_handle_t* rawHandle, uint32_t width, uint32_t height,
                          uint32_t layerCount, PixelFormat format, uint64_t usage, uint32_t stride,
                          buffer_handle_t* outHandle);

    status_t importBufferNoValidate(const native_handle_t* rawHandle, buffer_handle_t* outHandle);

    status_t freeBuffer(buffer_handle_t handle);

    void getTransportSize(buffer_handle_t handle,
            uint32_t* outTransportNumFds, uint32_t* outTransportNumInts);

    status_t lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr,
                  int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);

    status_t lockYCbCr(buffer_handle_t handle,
            uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr);

    status_t unlock(buffer_handle_t handle);

    status_t lockAsync(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr,
                       int fenceFd, int32_t* outBytesPerPixel = nullptr,
                       int32_t* outBytesPerStride = nullptr);

    status_t lockAsync(buffer_handle_t handle, uint64_t producerUsage, uint64_t consumerUsage,
                       const Rect& bounds, void** vaddr, int fenceFd,
                       int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);

    status_t lockAsyncYCbCr(buffer_handle_t handle,
            uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr,
            int fenceFd);

    status_t unlockAsync(buffer_handle_t handle, int *fenceFd);

    status_t isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
                         uint32_t layerCount, uint64_t usage, bool* outSupported);
    
    // .......

    const GrallocMapper& getGrallocMapper() const {
        return reinterpret_cast<const GrallocMapper&>(*mMapper);
    }

    Version getMapperVersion() const { return mMapperVersion; }

private:
    friend class Singleton<GraphicBufferMapper>;

    GraphicBufferMapper();

    std::unique_ptr<const GrallocMapper> mMapper;

    Version mMapperVersion;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

其中核心的成员是 std::unique_ptr<const GrallocMapper> mMapper;,GraphicBufferMapper 对外的所有功能都是通过该成员实现的,在构造函数中会对其进行初始化。

GraphicBuffer 的构造函数中调用到 GraphicBufferMapper::get()时,会调用到 GraphicBufferMapper 类的构造函数:

GraphicBufferMapper::GraphicBufferMapper() {
    mMapper = std::make_unique<const Gralloc5Mapper>();
    if (mMapper->isLoaded()) {
        mMapperVersion = Version::GRALLOC_5;
        return;
    }
    mMapper = std::make_unique<const Gralloc4Mapper>();
    if (mMapper->isLoaded()) {
        mMapperVersion = Version::GRALLOC_4;
        return;
    }
    mMapper = std::make_unique<const Gralloc3Mapper>();
    if (mMapper->isLoaded()) {
        mMapperVersion = Version::GRALLOC_3;
        return;
    }
    mMapper = std::make_unique<const Gralloc2Mapper>();
    if (mMapper->isLoaded()) {
        mMapperVersion = Version::GRALLOC_2;
        return;
    }

    LOG_ALWAYS_FATAL("gralloc-mapper is missing");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

这里会从高到低,依次去构造 Gralloc*Mapper 对象,最新的版本回去构造到 Gralloc5Mapper 对象。

Gralloc5Mapper 构造函数实现如下:

// /frameworks/native/libs/ui/Gralloc5.cpp

Gralloc5Mapper::Gralloc5Mapper() {
    mMapper = getInstance().mapper;
}

struct Gralloc5 {
    std::shared_ptr<IAllocator> allocator;
    AIMapper *mapper = nullptr;
};


static const Gralloc5 &getInstance() {
    // 前面已经调用过了
    static Gralloc5 instance = []() {
        // 获取 IAllocator Hal 服务代理端
        auto allocator = waitForAllocator();
        if (!allocator) {
            return Gralloc5{};
        }

        // 加载 mapper stable-c hal 库
        void *so = loadIMapperLibrary();
        if (!so) {
            return Gralloc5{};
        }

        // 加载 AIMapper_loadIMapper 函数
        auto loadIMapper = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
        // 拿到 hal 的对外接口 AIMapper
        AIMapper *mapper = nullptr;
        AIMapper_Error error = loadIMapper(&mapper);
        if (error != AIMAPPER_ERROR_NONE) {
            ALOGE("AIMapper_loadIMapper failed %d", error);
            return Gralloc5{};
        }
        return Gralloc5{std::move(allocator), mapper};
    }();
    return instance;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

waitForAllocator 会去获取一个 Allocator Hal 服务代理端对象,这个我们在后面说。

接着调用 loadIMapperLibrary 去加载 mapper stable-c hal 库:

static void *loadIMapperLibrary() {
    static void *imapperLibrary = []() -> void * {
        auto allocator = waitForAllocator();
        std::string mapperSuffix;
        auto status = allocator->getIMapperLibrarySuffix(&mapperSuffix);
        if (!status.isOk()) {
            ALOGE("Failed to get IMapper library suffix");
            return nullptr;
        }

        std::string lib_name = "mapper." + mapperSuffix + ".so";
        // 加载 so 库
        void *so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
        if (!so) {
            ALOGE("Failed to load %s", lib_name.c_str());
        }
        return so;
    }();
    return imapperLibrary;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

实际就是 dlopen 加载 so 库, Android 做了一些包装。

接着会调用 dlsym 去加载特定的符号 "AIMapper_loadIMapper",这个符号是一个函数指针,接着调用这个函数就能获取到操作 mapper 的接口 AIMapper 了。

// hardware/interfaces/graphics/mapper/stable-c/include/android/hardware/graphics/mapper/IMapper.h
typedef struct AIMapper {
    alignas(alignof(max_align_t)) AIMapper_Version version;
    AIMapperV5 v5;
} AIMapper;

typedef struct AIMapperV5 {
 
    AIMapper_Error (*_Nonnull importBuffer)(const native_handle_t* _Nonnull handle,
                                            buffer_handle_t _Nullable* _Nonnull outBufferHandle);

    AIMapper_Error (*_Nonnull freeBuffer)(buffer_handle_t _Nonnull buffer);

   
    AIMapper_Error (*_Nonnull getTransportSize)(buffer_handle_t _Nonnull buffer,
                                                uint32_t* _Nonnull outNumFds,
                                                uint32_t* _Nonnull outNumInts);

    
    AIMapper_Error (*_Nonnull lock)(buffer_handle_t _Nonnull buffer, uint64_t cpuUsage,
                                    ARect accessRegion, int acquireFence,
                                    void* _Nullable* _Nonnull outData);


    AIMapper_Error (*_Nonnull unlock)(buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence);

    
    AIMapper_Error (*_Nonnull flushLockedBuffer)(buffer_handle_t _Nonnull buffer);


    AIMapper_Error (*_Nonnull rereadLockedBuffer)(buffer_handle_t _Nonnull buffer);

    int32_t (*_Nonnull getMetadata)(buffer_handle_t _Nonnull buffer,
                                    AIMapper_MetadataType metadataType, void* _Nullable destBuffer,
                                    size_t destBufferSize);

    
    int32_t (*_Nonnull getStandardMetadata)(buffer_handle_t _Nonnull buffer,
                                            int64_t standardMetadataType,
                                            void* _Nullable destBuffer, size_t destBufferSize);


    AIMapper_Error (*_Nonnull setMetadata)(buffer_handle_t _Nonnull buffer,
                                           AIMapper_MetadataType metadataType,
                                           const void* _Nonnull metadata, size_t metadataSize);


    AIMapper_Error (*_Nonnull setStandardMetadata)(buffer_handle_t _Nonnull buffer,
                                                   int64_t standardMetadataType,
                                                   const void* _Nonnull metadata,
                                                   size_t metadataSize);


    AIMapper_Error (*_Nonnull listSupportedMetadataTypes)(
            const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
            size_t* _Nonnull outNumberOfDescriptions);


    AIMapper_Error (*_Nonnull dumpBuffer)(buffer_handle_t _Nonnull buffer,
                                          AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
                                          void* _Null_unspecified context);


    AIMapper_Error (*_Nonnull dumpAllBuffers)(
            AIMapper_BeginDumpBufferCallback _Nonnull beginDumpCallback,
            AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
            void* _Null_unspecified context);


    AIMapper_Error (*_Nonnull getReservedRegion)(buffer_handle_t _Nonnull buffer,
                                                 void* _Nullable* _Nonnull outReservedRegion,
                                                 uint64_t* _Nonnull outReservedSize);

} AIMapperV5;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

AIMapper 中有一个 AIMapperV5 成员,里面有一堆函数,这些函数就是 mapper hal 对外提供的功能。mapper hal 本身是个芯片厂商自己去实现的,通常是闭源的,我们主要了解其对外的接口即可。

我们接着回到 GraphicBuffer 构造函数中,构造函数中会调用 initWithSize 函数:

status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,
        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
        std::string requestorName)
{
    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
    uint32_t outStride = 0;
    status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
            inUsage, &handle, &outStride, mId,
            std::move(requestorName));
    if (err == NO_ERROR) {
        mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);

        width = static_cast<int>(inWidth);
        height = static_cast<int>(inHeight);
        format = inFormat;
        layerCount = inLayerCount;
        usage = inUsage;
        usage_deprecated = int(usage);
        stride = static_cast<int>(outStride);
    }
    return err;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

这里会通过 GraphicBufferAllocator::get() 获取一个 GraphicBufferAllocator 对象。

GraphicBufferAllocator 是一个单例类:

// /frameworks/native/libs/ui/include_vndk/ui/GraphicBufferAllocator.h
class GraphicBufferAllocator : public Singleton<GraphicBufferAllocator>
{
    //......
    GraphicBufferMapper& mMapper;
    std::unique_ptr<const GrallocAllocator> mAllocator;
}
1
2
3
4
5
6
7

GraphicBufferAllocator::get() 会调用到其构造函数:

// /frameworks/native/libs/ui/GraphicBufferAllocator.cpp

// 构造函数
GraphicBufferAllocator::GraphicBufferAllocator() : mMapper(GraphicBufferMapper::getInstance()) {
    switch (mMapper.getMapperVersion()) {
        case GraphicBufferMapper::GRALLOC_5:
            mAllocator = std::make_unique<const Gralloc5Allocator>(
                    reinterpret_cast<const Gralloc5Mapper&>(mMapper.getGrallocMapper()));
            break;
        case GraphicBufferMapper::GRALLOC_4:
            mAllocator = std::make_unique<const Gralloc4Allocator>(
                    reinterpret_cast<const Gralloc4Mapper&>(mMapper.getGrallocMapper()));
            break;
        case GraphicBufferMapper::GRALLOC_3:
            mAllocator = std::make_unique<const Gralloc3Allocator>(
                    reinterpret_cast<const Gralloc3Mapper&>(mMapper.getGrallocMapper()));
            break;
        case GraphicBufferMapper::GRALLOC_2:
            mAllocator = std::make_unique<const Gralloc2Allocator>(
                    reinterpret_cast<const Gralloc2Mapper&>(mMapper.getGrallocMapper()));
            break;
    }
    LOG_ALWAYS_FATAL_IF(!mAllocator->isLoaded(),
                        "Failed to load matching allocator for mapper version %d",
                        mMapper.getMapperVersion());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

GraphicBufferMapper::getInstance() 会去获取 GraphicBufferMapper 对象,这个在前面已经分析过了。

接下来会依次初始化 Gralloc*Allocator 对象,最新版本会初始化 Gralloc5Allocator。

Gralloc5Allocator 的定义如下:

// /frameworks/native/libs/ui/include/ui/Gralloc5.h
typedef const native_handle_t* buffer_handle_t;

// /frameworks/native/libs/ui/include/ui/Gralloc5.h
class Gralloc5Allocator : public GrallocAllocator {
public:
    Gralloc5Allocator(const Gralloc5Mapper &mapper);

    [[nodiscard]] bool isLoaded() const override;

    [[nodiscard]] std::string dumpDebugInfo(bool less) const override;

    [[nodiscard]] status_t allocate(std::string requestorName, uint32_t width, uint32_t height,
                                    PixelFormat format, uint32_t layerCount, uint64_t usage,
                                    uint32_t bufferCount, uint32_t *outStride,
                                    buffer_handle_t *outBufferHandles,
                                    bool importBuffers) const override;

private:
    const Gralloc5Mapper &mMapper;
    // Allocator aidl hal 的代理端对象
    std::shared_ptr<aidl::android::hardware::graphics::allocator::IAllocator> mAllocator;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

GrallocAllocator 中有一个 IAllocator 成员,在构造函数中会被赋值为 Allocator aidl hal 的代理端对象。

Gralloc5Allocator 的构造函数实现如下:

Gralloc5Allocator::Gralloc5Allocator(const Gralloc5Mapper &mapper) : mMapper(mapper) {
    mAllocator = getInstance().allocator;
}

struct Gralloc5 {
    std::shared_ptr<IAllocator> allocator;
    AIMapper *mapper = nullptr;
};

static const Gralloc5 &getInstance() {
    static Gralloc5 instance = []() {
        // 获取 IAllocator 代理端
        auto allocator = waitForAllocator();
        if (!allocator) {
            return Gralloc5{};
        }
        // 加载 stable-c hal 库
        void *so = loadIMapperLibrary();
        if (!so) {
            return Gralloc5{};
        }
        auto loadIMapper = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
        AIMapper *mapper = nullptr;
        AIMapper_Error error = loadIMapper(&mapper);
        if (error != AIMAPPER_ERROR_NONE) {
            ALOGE("AIMapper_loadIMapper failed %d", error);
            return Gralloc5{};
        }
        return Gralloc5{std::move(allocator), mapper};
    }();
    return instance;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

调用 waitForAllocator 获取 IAllocator 代理端。

static std::shared_ptr<IAllocator> waitForAllocator() {
    if (__builtin_available(android 31, *)) {
        if (!AServiceManager_isDeclared(kIAllocatorServiceName.c_str())) {
            return nullptr;
        }
        auto allocator = IAllocator::fromBinder(
                ndk::SpAIBinder(AServiceManager_waitForService(kIAllocatorServiceName.c_str())));
        if (!allocator) {
            ALOGE("AIDL IAllocator declared but failed to get service");
            return nullptr;
        }

        int32_t version = 0;
        if (!allocator->getInterfaceVersion(&version).isOk()) {
            ALOGE("Failed to query interface version");
            return nullptr;
        }
        if (version < kIAllocatorMinimumVersion) {
            return nullptr;
        }
        return allocator;
    } else {
        // TODO: LOG_ALWAYS_FATAL("libui is not backwards compatible");
        return nullptr;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

调用 AServiceManager_waitForService 获取到 IAllocator 代理端对象并返回。

IAllocator hal 对应的 aidl 定义如下:

// hardware/interfaces/graphics/allocator/aidl/android/hardware/graphics/allocator/IAllocator.aidl
interface IAllocator {
    AllocationResult allocate(in byte[] descriptor, in int count);
    AllocationResult allocate2(in BufferDescriptorInfo descriptor, in int count);
    boolean isSupported(in BufferDescriptorInfo descriptor);
    String getIMapperLibrarySuffix();
}
1
2
3
4
5
6
7

在 initWithSize 中接着就会调用 GraphicBufferAllocator::allocate 去分配内存:

status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, PixelFormat format,
                                          uint32_t layerCount, uint64_t usage,
                                          buffer_handle_t* handle, uint32_t* stride,
                                          std::string requestorName) {
    return allocateHelper(width, height, format, layerCount, usage, handle, stride, requestorName,
                          true);
}

status_t GraphicBufferAllocator::allocateHelper(uint32_t width, uint32_t height, PixelFormat format,
                                                uint32_t layerCount, uint64_t usage,
                                                buffer_handle_t* handle, uint32_t* stride,
                                                std::string requestorName, bool importBuffer) {
    ATRACE_CALL();

    // make sure to not allocate a N x 0 or 0 x N buffer, since this is
    // allowed from an API stand-point allocate a 1x1 buffer instead.
    if (!width || !height)
        width = height = 1;

    const uint32_t bpp = bytesPerPixel(format);
    if (std::numeric_limits<size_t>::max() / width / height < static_cast<size_t>(bpp)) {
        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
              "usage %" PRIx64 ": Requesting too large a buffer size",
              width, height, layerCount, format, usage);
        return BAD_VALUE;
    }

    // Ensure that layerCount is valid.
    if (layerCount < 1) {
        layerCount = 1;
    }

    // TODO(b/72323293, b/72703005): Remove these invalid bits from callers
    usage &= ~static_cast<uint64_t>((1 << 10) | (1 << 13));

    // 远程调用 hal
    status_t error = mAllocator->allocate(requestorName, width, height, format, layerCount, usage,
                                          1, stride, handle, importBuffer);
    
    if (error != NO_ERROR) {
        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
              "usage %" PRIx64 ": %d",
              width, height, layerCount, format, usage, error);
        return error;
    }

    if (!importBuffer) {
        return NO_ERROR;
    }

    size_t bufSize;

    // if stride has no meaning or is too large,
    // approximate size with the input width instead
    if ((*stride) != 0 &&
        std::numeric_limits<size_t>::max() / height / (*stride) < static_cast<size_t>(bpp)) {
        bufSize = static_cast<size_t>(width) * height * bpp;
    } else {
        bufSize = static_cast<size_t>((*stride)) * height * bpp;
    }

    Mutex::Autolock _l(sLock);
    KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
    alloc_rec_t rec;
    rec.width = width;
    rec.height = height;
    rec.stride = *stride;
    rec.format = format;
    rec.layerCount = layerCount;
    rec.usage = usage;
    rec.size = bufSize;
    rec.requestorName = std::move(requestorName);
    list.add(*handle, rec);

    return NO_ERROR;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

实际这里是远程调用 IAllocator hal 来分配内存,返回值中有一个 handle 中就有一个 fd 成员,前面说过 fd 是 buffer 的索引。

IAllocator hal 一般是芯片厂商来做实现,通常是闭源的,我们主要关心其对外接口。

# 2.2 GraphicBuffer lock 过程分析

status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel,
                             int32_t* outBytesPerStride) {
    const Rect lockBounds(width, height);
    status_t res = lock(inUsage, lockBounds, vaddr, outBytesPerPixel, outBytesPerStride);
    return res;
}

status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr,
                             int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
    if (rect.left < 0 || rect.right  > width ||
        rect.top  < 0 || rect.bottom > height) {
        ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
                rect.left, rect.top, rect.right, rect.bottom,
                width, height);
        return BAD_VALUE;
    }

    status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr, outBytesPerPixel,
                                          outBytesPerStride);

    return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds,
                                   void** vaddr, int32_t* outBytesPerPixel,
                                   int32_t* outBytesPerStride) {
    return lockAsync(handle, usage, bounds, vaddr, -1, outBytesPerPixel, outBytesPerStride);
}

status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint32_t usage, const Rect& bounds,
                                        void** vaddr, int fenceFd, int32_t* outBytesPerPixel,
                                        int32_t* outBytesPerStride) {
    return lockAsync(handle, usage, usage, bounds, vaddr, fenceFd, outBytesPerPixel,
                     outBytesPerStride);
}

status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, uint64_t producerUsage,
                                        uint64_t consumerUsage, const Rect& bounds, void** vaddr,
                                        int fenceFd, int32_t* outBytesPerPixel,
                                        int32_t* outBytesPerStride) {
    ATRACE_CALL();

    const uint64_t usage = static_cast<uint64_t>(
            android_convertGralloc1To0Usage(producerUsage, consumerUsage));
    return mMapper->lock(handle, usage, bounds, fenceFd, vaddr, outBytesPerPixel,
                         outBytesPerStride);
}

status_t Gralloc5Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect &bounds,
                              int acquireFence, void **outData, int32_t *outBytesPerPixel,
                              int32_t *outBytesPerStride) const {
    std::vector<ui::PlaneLayout> planeLayouts;
    status_t err = getPlaneLayouts(bufferHandle, &planeLayouts);

    if (err == NO_ERROR && !planeLayouts.empty()) {
        if (outBytesPerPixel) {
            int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
            for (const auto &planeLayout : planeLayouts) {
                if (bitsPerPixel != planeLayout.sampleIncrementInBits) {
                    bitsPerPixel = -1;
                }
            }
            if (bitsPerPixel >= 0 && bitsPerPixel % 8 == 0) {
                *outBytesPerPixel = bitsPerPixel / 8;
            } else {
                *outBytesPerPixel = -1;
            }
        }
        if (outBytesPerStride) {
            int32_t bytesPerStride = planeLayouts.front().strideInBytes;
            for (const auto &planeLayout : planeLayouts) {
                if (bytesPerStride != planeLayout.strideInBytes) {
                    bytesPerStride = -1;
                }
            }
            if (bytesPerStride >= 0) {
                *outBytesPerStride = bytesPerStride;
            } else {
                *outBytesPerStride = -1;
            }
        }
    }

    auto status = mMapper->v5.lock(bufferHandle, usage, bounds, acquireFence, outData);

    ALOGW_IF(status != AIMAPPER_ERROR_NONE, "lock(%p, ...) failed: %d", bufferHandle, status);
    return static_cast<status_t>(status);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

实际调用 hal 层去做 mmap 操作,hal 层由芯片厂商来实现,通常是闭源的。

上述类的整体结构如下:

GraphicBuffer相关类结构

# 3. Producer 对象 queueBuffer 过程分析

App 通过调用 dequeueBuffer 获取到一个可用的 buffer 后,就可以往这个 buffer 中填充数据了,在我们的 demo 中这一过程是在fillRGBA8Buffer函数内完成的。

void fillRGBA8Buffer(uint8_t* img, int width, int height, int stride, int r, int g, int b) {
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            uint8_t* pixel = img + (4 * (y*stride + x));
            pixel[0] = r;
            pixel[1] = g;
            pixel[2] = b;
            pixel[3] = 0;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11

填充好数据后,就要把这个 buffer 再返还给 BufferQueue,调用的方法是 queueBuffer。

        // 3. queue the buffer to display
        IGraphicBufferProducer::QueueBufferOutput qbOutput;
        IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
                                                       HAL_DATASPACE_UNKNOWN, {},
                                                       NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
                                                       Fence::NO_FENCE);
        igbProducer->queueBuffer(slot, input, &qbOutput);
1
2
3
4
5
6
7

这里把相关参数封装到 QueueBufferInput 中,其中比较重要的是最后一个 Fence,这里做了简化,使用 Fence::NO_FENCE,实际的 Android 代码中,这里的 Fence 是在渲染开始之前构建的,渲染完成后会调用 Fence 的 signal 函数,告诉其他组件可以使用 buffer 了。

queueBuffer() 的内部操作流程如下图所示:

20190811210412775

动图来自 https://blog.csdn.net/hexiaolong2009/article/details/99225637

整体流程可以分为两步:

  1. queueBuffer() 根据调用者传入的 slot 参数,将其对应的 BufferSlot 状态从 DEQUEUED 修改为 QUEUED,并根据该 BufferSlot 的信息生成一个 BufferItem 对象,然后添加到 mQueue 队列中。
  2. 调用 Consumer 的 Listener 监听函数,通知 Consumer 可以调用 acquireBuffer 了。

接着看 queueBuffer 函数的具体实现:

status_t BufferQueueProducer::queueBuffer(int slot,
        const QueueBufferInput &input, QueueBufferOutput *output) {
    ATRACE_CALL();
    ATRACE_BUFFER_INDEX(slot);

    int64_t requestedPresentTimestamp;
    bool isAutoTimestamp;
    android_dataspace dataSpace;
    Rect crop(Rect::EMPTY_RECT);
    int scalingMode;
    uint32_t transform;
    uint32_t stickyTransform;
    sp<Fence> acquireFence;
    bool getFrameTimestamps = false;
    // 保存Surface传递过来的input里面封装的buffer信息
    input.deflate(&requestedPresentTimestamp, &isAutoTimestamp, &dataSpace,
            &crop, &scalingMode, &transform, &acquireFence, &stickyTransform,
            &getFrameTimestamps);
    const Region& surfaceDamage = input.getSurfaceDamage();
    const HdrMetadata& hdrMetadata = input.getHdrMetadata();

    if (acquireFence == nullptr) {
        BQ_LOGE("queueBuffer: fence is NULL");
        return BAD_VALUE;
    }

    auto acquireFenceTime = std::make_shared<FenceTime>(acquireFence);

    switch (scalingMode) {
        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
            break;
        default:
            BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
            return BAD_VALUE;
    }

    // 回调接口,用于通知consumer
    sp<IConsumerListener> frameAvailableListener;
    sp<IConsumerListener> frameReplacedListener;
    int callbackTicket = 0;
    uint64_t currentFrameNumber = 0;
    BufferItem item;
    { // Autolock scope
        std::lock_guard<std::mutex> lock(mCore->mMutex);

        if (mCore->mIsAbandoned) {
            BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
            return NO_INIT;
        }

        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
            BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
            return NO_INIT;
        }

        if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
            BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
                    slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
            return BAD_VALUE;
        } else if (!mSlots[slot].mBufferState.isDequeued()) {
            BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
                    "(state = %s)", slot, mSlots[slot].mBufferState.string());
            return BAD_VALUE;
        } else if (!mSlots[slot].mRequestBufferCalled) {
            BQ_LOGE("queueBuffer: slot %d was queued without requesting "
                    "a buffer", slot);
            return BAD_VALUE;
        }

        // If shared buffer mode has just been enabled, cache the slot of the
        // first buffer that is queued and mark it as the shared buffer.
        if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
                BufferQueueCore::INVALID_BUFFER_SLOT) {
            mCore->mSharedBufferSlot = slot;
            mSlots[slot].mBufferState.mShared = true;
        }

        BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
                " validHdrMetadataTypes=0x%x crop=[%d,%d,%d,%d] transform=%#x scale=%s",
                slot, mCore->mFrameCounter + 1, requestedPresentTimestamp, dataSpace,
                hdrMetadata.validTypes, crop.left, crop.top, crop.right, crop.bottom,
                transform,
                BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));

        // 当前queue的具体GraphicBuffer
        const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
        Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
        Rect croppedRect(Rect::EMPTY_RECT);
        crop.intersect(bufferRect, &croppedRect);
        if (croppedRect != crop) {
            BQ_LOGE("queueBuffer: crop rect is not contained within the "
                    "buffer in slot %d", slot);
            return BAD_VALUE;
        }

        // Override UNKNOWN dataspace with consumer default
        if (dataSpace == HAL_DATASPACE_UNKNOWN) {
            dataSpace = mCore->mDefaultBufferDataSpace;
        }

        mSlots[slot].mFence = acquireFence;
        // 改变入队的BufferSlot的状态为QUEUED
        mSlots[slot].mBufferState.queue();

        // Increment the frame counter and store a local version of it
        // for use outside the lock on mCore->mMutex.
        ++mCore->mFrameCounter;
        currentFrameNumber = mCore->mFrameCounter;
        mSlots[slot].mFrameNumber = currentFrameNumber;

        // 把BufferSlot中的信息封装为BufferItem,后续会把这个BufferItem加入到队列中
        item.mAcquireCalled = mSlots[slot].mAcquireCalled;
        item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
        item.mCrop = crop;
        item.mTransform = transform &
                ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
        item.mTransformToDisplayInverse =
                (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
        item.mScalingMode = static_cast<uint32_t>(scalingMode);
        item.mTimestamp = requestedPresentTimestamp;
        item.mIsAutoTimestamp = isAutoTimestamp;
        item.mDataSpace = dataSpace;
        item.mHdrMetadata = hdrMetadata;
        item.mFrameNumber = currentFrameNumber;
        item.mSlot = slot;
        item.mFence = acquireFence;
        item.mFenceTime = acquireFenceTime;
        item.mIsDroppable = mCore->mAsyncMode ||
                (mConsumerIsSurfaceFlinger && mCore->mQueueBufferCanDrop) ||
                (mCore->mLegacyBufferDrop && mCore->mQueueBufferCanDrop) ||
                (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
        item.mSurfaceDamage = surfaceDamage;
        item.mQueuedBuffer = true;
        item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
        item.mApi = mCore->mConnectedApi;

        mStickyTransform = stickyTransform;

        // Cache the shared buffer data so that the BufferItem can be recreated.
        if (mCore->mSharedBufferMode) {
            mCore->mSharedBufferCache.crop = crop;
            mCore->mSharedBufferCache.transform = transform;
            mCore->mSharedBufferCache.scalingMode = static_cast<uint32_t>(
                    scalingMode);
            mCore->mSharedBufferCache.dataspace = dataSpace;
        }

        output->bufferReplaced = false;
        if (mCore->mQueue.empty()) {
            // When the queue is empty, we can ignore mDequeueBufferCannotBlock
            // and simply queue this buffer
            // // 如果mQueue队列为空,则直接push进入这个mQueue,不用考虑阻塞
            mCore->mQueue.push_back(item);
            // 拿到回调对象
            frameAvailableListener = mCore->mConsumerListener;
        } else {
            // When the queue is not empty, we need to look at the last buffer
            // in the queue to see if we need to replace it
            // 判断最后一个BufferItem是否可以丢弃 
            const BufferItem& last = mCore->mQueue.itemAt(
                    mCore->mQueue.size() - 1);
            if (last.mIsDroppable) {

                if (!last.mIsStale) {
                    mSlots[last.mSlot].mBufferState.freeQueued();

                    // After leaving shared buffer mode, the shared buffer will
                    // still be around. Mark it as no longer shared if this
                    // operation causes it to be free.
                    if (!mCore->mSharedBufferMode &&
                            mSlots[last.mSlot].mBufferState.isFree()) {
                        mSlots[last.mSlot].mBufferState.mShared = false;
                    }
                    // Don't put the shared buffer on the free list.
                    if (!mSlots[last.mSlot].mBufferState.isShared()) {
                        mCore->mActiveBuffers.erase(last.mSlot);
                        mCore->mFreeBuffers.push_back(last.mSlot);
                        output->bufferReplaced = true;
                    }
                }

                // Make sure to merge the damage rect from the frame we're about
                // to drop into the new frame's damage rect.
                if (last.mSurfaceDamage.bounds() == Rect::INVALID_RECT ||
                    item.mSurfaceDamage.bounds() == Rect::INVALID_RECT) {
                    item.mSurfaceDamage = Region::INVALID_REGION;
                } else {
                    item.mSurfaceDamage |= last.mSurfaceDamage;
                }
                // 用当前BufferItem,替换了队列最后一个BufferItem
                // Overwrite the droppable buffer with the incoming one
                mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
                // 拿到回调对象
                frameReplacedListener = mCore->mConsumerListener;
            } else {
                // 直接push进入这个mQueue
                mCore->mQueue.push_back(item);
                // 拿到回调对象
                frameAvailableListener = mCore->mConsumerListener;
            }
        }

        mCore->mBufferHasBeenQueued = true;
        mCore->mDequeueCondition.notify_all();
        mCore->mLastQueuedSlot = slot;

        output->width = mCore->mDefaultWidth;
        output->height = mCore->mDefaultHeight;
        output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
        output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size());
        output->nextFrameNumber = mCore->mFrameCounter + 1;

        ATRACE_INT(mCore->mConsumerName.string(),
                static_cast<int32_t>(mCore->mQueue.size()));
#ifndef NO_BINDER
        mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size());
#endif
        // Take a ticket for the callback functions
        callbackTicket = mNextCallbackTicket++;

        VALIDATE_CONSISTENCY();
    } // Autolock scope

    // It is okay not to clear the GraphicBuffer when the consumer is SurfaceFlinger because
    // it is guaranteed that the BufferQueue is inside SurfaceFlinger's process and
    // there will be no Binder call
    if (!mConsumerIsSurfaceFlinger) {
        item.mGraphicBuffer.clear();
    }

    // Update and get FrameEventHistory.
    nsecs_t postedTime = systemTime(SYSTEM_TIME_MONOTONIC);
    NewFrameEventsEntry newFrameEventsEntry = {
        currentFrameNumber,
        postedTime,
        requestedPresentTimestamp,
        std::move(acquireFenceTime)
    };
    addAndGetFrameTimestamps(&newFrameEventsEntry,
            getFrameTimestamps ? &output->frameTimestamps : nullptr);

    // Call back without the main BufferQueue lock held, but with the callback
    // lock held so we can ensure that callbacks occur in order

    int connectedApi;
    sp<Fence> lastQueuedFence;

    { // scope for the lock
        std::unique_lock<std::mutex> lock(mCallbackMutex);
        while (callbackTicket != mCurrentCallbackTicket) {
            mCallbackCondition.wait(lock);
        }
        //调用回调对象通知 consumer
        if (frameAvailableListener != nullptr) {
            frameAvailableListener->onFrameAvailable(item);
        } else if (frameReplacedListener != nullptr) {
            frameReplacedListener->onFrameReplaced(item);
        }

        connectedApi = mCore->mConnectedApi;
        lastQueuedFence = std::move(mLastQueueBufferFence);

        mLastQueueBufferFence = std::move(acquireFence);
        mLastQueuedCrop = item.mCrop;
        mLastQueuedTransform = item.mTransform;

        ++mCurrentCallbackTicket;
        mCallbackCondition.notify_all();
    }

    // Wait without lock held
    if (connectedApi == NATIVE_WINDOW_API_EGL) {
        // Waiting here allows for two full buffers to be queued but not a
        // third. In the event that frames take varying time, this makes a
        // small trade-off in favor of latency rather than throughput.
        lastQueuedFence->waitForever("Throttling EGL Production");
    }

    return NO_ERROR;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

queueBuffer 的流程主要做了这两件事情:

  • 将对应 BufferSlot 状态从 DEQUEUEED 设置为 QUEUED;
  • 创建 BufferItem 对象,并将 GraphicBuffer 的数据复制给 BufferItem,并入队到 BufferQueueCore 的 mQueue 队列中,这样可以方便图像消费者直接按先进先出的顺序从 mQueue 队列取出 GraphicBuffer 使用;

到此 queueBuffer 就分析完了。其中会调用了 frameAvailableListener->onFrameAvailable(item) 的回调接口,来通知 consumer 消费数据,那么这个回调接口是在何时被传入的,回调函数的具体操作是什么?这个我们就留在下一节再来讲解了

# 参考资料